package com.jju.howe.howeassistant.engine;

import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.TextView;

import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.VoiceWakeuper;
import com.iflytek.cloud.WakeuperListener;
import com.iflytek.cloud.WakeuperResult;
import com.iflytek.cloud.util.ResourceUtil;
import com.jju.howe.howeassistant.util.ToastUtil;



public class AssistantEngine {

    //上下文
    private Context context;


    //语音识别类
    private SpeechRecognizer speechRecognizer;

    //判断初始化状态的数值
    private int state = 0;

    //测试模式
    private boolean testMode = false;
    private boolean ivwOff = false;

    //听到的结果
    private StringBuffer listenBuffer = new StringBuffer();


    //文字转语音类
    private Speaker speaker;

    //监听命令类
    private VoiceWakeuper voiceWakeuper = null;

    //所有谈话都存在这里面
    private StringBuffer talkList = new StringBuffer();

    //显示谈话的文本框
    private TextView voiceText;


    private void initSpeaker() {
        state = state + 1;
        // 语音输出
        speaker = new Speaker(this.context);

        // 唤醒器
        if (!ivwOff) {
            voiceWakeuper = VoiceWakeuper.createWakeuper(this.context, new InitListener() {
                @Override
                public void onInit(int i) {
                    Log.d("aa", "==onInit i:" + i);
                }
            });
        }
    }

    // 构造函数
    public AssistantEngine(Context context, TextView view_) {
        this.context = context;
        talkList.setLength(0);
        this.voiceText = view_;

        // 状态判断的变量，如果state后续中小于某个值就会无法执行
        state = 0;

        initSpeaker();
    }

    /**
     * 改变语音栏位的文字
     */

    public void loadTalk(String talks, TextView view) {
        if (null == view) {
            return;
        }
        talkList.delete(0, talkList.length());
        talkList.append(talks);
        view.setText(talkList.toString());
    }


    // 唤醒方法封装
    public void initWake() {
        if (ivwOff)
            return;

        if (voiceWakeuper == null) {
            voiceWakeuper = VoiceWakeuper.createWakeuper(context, null);
        }

        // 唤醒词启动
        voiceWakeuper = VoiceWakeuper.getWakeuper();
        if (voiceWakeuper != null) {

            int MAX = 3000;
            int MIN = 0;
            int curThresh = 1450; // 门限值
            String keep_alive = "1";
            String ivwNetMode = "0";

            // 清空参数
            voiceWakeuper.setParameter(SpeechConstant.PARAMS, null);
            Log.d("________TEST_______", "PARAMS");
            // 唤醒门限值，根据资源携带的唤醒词个数按照“id:门限;id:门限”的格式传入
            voiceWakeuper.setParameter(SpeechConstant.IVW_THRESHOLD, "0:" + curThresh);
            Log.d("________TEST_______", "IVW_THRESHOLD");
            // 设置唤醒模式
            voiceWakeuper.setParameter(SpeechConstant.IVW_SST, "wakeup");
            Log.d("________TEST_______", "IVW_SST");
            // 设置持续进行唤醒
            voiceWakeuper.setParameter(SpeechConstant.KEEP_ALIVE, keep_alive);
            Log.d("________TEST_______", "KEEP_ALIVE");
            // 设置闭环优化网络模式
            voiceWakeuper.setParameter(SpeechConstant.IVW_NET_MODE, ivwNetMode);
            Log.d("________TEST_______", "IVW_NET_MODE");
            // 设置唤醒资源路径
            voiceWakeuper.setParameter(SpeechConstant.IVW_RES_PATH, getResource());
            Log.d("________TEST_______", "IVW_RES_PATH");
            // 设置唤醒录音保存路径，保存最近一分钟的音频
            voiceWakeuper.setParameter(SpeechConstant.IVW_AUDIO_PATH, Environment.getExternalStorageDirectory().getPath() + "/msc/ivw.wav");
            Log.d("________TEST_______", "IVW_AUDIO_PATH");
            voiceWakeuper.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
            Log.d("________TEST_______", "AUDIO_FORMAT");
            // 如有需要，设置 NOTIFY_RECORD_DATA 以实时通过 onEvent 返回录音音频流字节
            //mIvw.setParameter( SpeechConstant.NOTIFY_RECORD_DATA, "1" );
            // 启动唤醒
            /*	mIvw.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");*/

            voiceWakeuper.startListening(mWakeuperListener);
				/*File file = new File(Environment.getExternalStorageDirectory().getPath() + "/msc/ivw1.wav");
				byte[] byetsFromFile = getByetsFromFile(file);
				mIvw.writeAudio(byetsFromFile,0,byetsFromFile.length);*/
            //	mIvw.stopListening();
        } else {
            ToastUtil.show(context, "唤醒未初始化", 1000);
        }
    }

    // 唤醒暂停
    public void wake_pause() {
        if (ivwOff)
            return;
        if (voiceWakeuper != null) {
            voiceWakeuper.stopListening();
        }
    }

    // 唤醒保持继续
    public void wake_go_on() {
        if (ivwOff)
            return;
        if (voiceWakeuper != null) {
            voiceWakeuper.startListening(mWakeuperListener);
        }
    }

    // 统一构造封装的听写方法
    public void assistantListen() {
        initListener();
        listenResult();
    }

    // 听写初始化
    public void initListener() {
        //使得ivw直接中断
        if (!ivwOff && voiceWakeuper != null) {
            voiceWakeuper.stopListening();
        }

        if (state < 1) {
            ToastUtil.show(context, "初始化错误", 1000);
            return;
        }


        speechRecognizer = SpeechRecognizer.createRecognizer(context, new InitListener() {
            @Override
            public void onInit(int i) {
                Log.d("aa","==speechRecognizer onInit:"+i);
            }
        });
        if (speechRecognizer == null) {
            ToastUtil.show(context, "init recognizer fail", 1000);
        } else {
            // 状态判断的变量，如果state后续中小于某个值就会无法执行
            state = state + 10;

            //设置语法ID和 SUBJECT 为空，以免因之前有语法调用而设置了此参数；或直接清空所有参数，具体可参考 DEMO 的示例。
            speechRecognizer.setParameter(SpeechConstant.CLOUD_GRAMMAR, null);
            speechRecognizer.setParameter(SpeechConstant.SUBJECT, null);
            //设置返回结果格式，目前支持json,xml以及plain 三种格式，其中plain为纯听写文本内容
            speechRecognizer.setParameter(SpeechConstant.RESULT_TYPE, "plain");
            //此处engineType为“cloud”
            speechRecognizer.setParameter(SpeechConstant.ENGINE_TYPE, "cloud");
            //设置语音输入语言，zh_cn为简体中文
            speechRecognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
            //设置结果返回语言
            speechRecognizer.setParameter(SpeechConstant.ACCENT, "mandarin");
            // 设置语音前端点:静音超时时间，单位ms，即用户多长时间不说话则当做超时处理
            //取值范围{1000～10000}
            speechRecognizer.setParameter(SpeechConstant.VAD_BOS, "2000");
            //设置语音后端点:后端点静音检测时间，单位ms，即用户停止说话多长时间内即认为不再输入，
            //自动停止录音，范围{0~10000}
            speechRecognizer.setParameter(SpeechConstant.VAD_EOS, "1000");
            //设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
            speechRecognizer.setParameter(SpeechConstant.ASR_PTT, "1");
        }
    }

//    VoiceService.CallBack<String> stringCallBack;

    // 开始听写，获取音频和文字、分类
    public void listenResult() {
        if (state < 11) {
            ToastUtil.show(context, "初始化错误", 1000);
            return;
        }

        listenBuffer.setLength(0);
        //监听器初始化
        RecognizerListener mRecogListener = new RecognizerListener() {
            @Override
            public void onVolumeChanged(int i, byte[] bytes) {

            }

            @Override
            public void onBeginOfSpeech() {
                ToastUtil.show(context, "请说话", 1000);

            }

            @Override
            public void onEndOfSpeech() {
                if (testMode) {
                    if (listenBuffer.length() > 1)
                        ToastUtil.show(context, listenBuffer.append(" -testMode").toString(), 2000);
                } else {
                    ToastUtil.show(context, "录音结束", 300);
                }


                Log.d("I_FLY", "onEndOfSpeech: ");
            }

            @Override
            public void onResult(RecognizerResult recognizerResult, boolean b) {


                if (recognizerResult != null) {
                    Log.d("I_FLY", "onResult b:" + b + " \n:" + recognizerResult.getResultString());
                    if (b) {
                        listenBuffer.append(recognizerResult.getResultString());
                    } else {
                        listenBuffer.append(recognizerResult.getResultString());
                    }


                    loadTalk(listenBuffer.toString(), voiceText);
                    // 读出回应（测试模式下为读出使用者的命令）
                    // TODO 加上非测试的输出
                    speaker.doSpeech(listenBuffer.toString());
                    if (stringCallBack!=null){
                        stringCallBack.call(listenBuffer.toString());
                    }
                }
            }

            @Override
            public void onError(SpeechError speechError) {
                Log.d("aa", "==onError:" + speechError.toString());
                ToastUtil.show(context, "意外错误，请重试：" + speechError.toString(), 1000);
            }

            @Override
            public void onEvent(int i, int i1, int i2, Bundle bundle) {

            }
        };

        //开始识别
        speechRecognizer.startListening(mRecogListener);
    }


    public void speak(String ss) {
        if (speaker != null) {
            speaker.doSpeech(ss);
        }
    }

    // 唤醒词使用的路径寻求函数
    private String getResource() {
        //return "ivw/"+ context_.getString(R.string.app_id) +".jet";
        final String resPath = ResourceUtil.generateResourcePath(context, ResourceUtil.RESOURCE_TYPE.assets, "5eb4d530.jet");
        return resPath;
    }

    // 唤醒监听器的定义
    private WakeuperListener mWakeuperListener = new WakeuperListener() {
        @Override
        public void onBeginOfSpeech() {

        }

        @Override
        public void onResult(WakeuperResult wakeuperResult) {
            // 唤醒成功先打报告，后面再根据置信度确定是否 CALL button 去开始录音
            Log.d("TAG", "onResult");
            // 先立一个条件，未来需要再改
            if (true) {
                if (!ivwOff) {
                    voiceWakeuper.stopListening();
                }
                assistantListen();
            }

        }

        @Override
        public void onError(SpeechError speechError) {

        }

        @Override
        public void onEvent(int i, int i1, int i2, Bundle bundle) {

        }

        @Override
        public void onVolumeChanged(int i) {

        }
    };

    // 急停语音
    public void stopListener() {
        if (speechRecognizer.isListening()) {
            speechRecognizer.stopListening();
        }
    }

    public CallBack<String> stringCallBack;

    public CallBack<String> getStringCallBack() {
        return stringCallBack;
    }

    public void setStringCallBack(CallBack<String> stringCallBack) {
        this.stringCallBack = stringCallBack;
    }

    public interface CallBack<T>{
        public void call(String ss);
    }

}
